package de.ba_rm.java.password.checker.view;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstants;
import info.clearthought.layout.TableLayoutConstraints;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;

import org.apache.commons.lang3.CharUtils;

import de.ba_rm.java.password.checker.Controller;
import de.ba_rm.java.password.checker.Messages;

/**
 * 
 * @author sebastian.toense@gmail.com
 *
 */
public class View extends JFrame {
	
	/** @see java.io.Serializable */
	private static final long serialVersionUID = -2320063862694261799L;

	private static final String TEXTFIELD_TOOL_TIP = Messages.getString("View.0"); //$NON-NLS-1$
	
	public static final String ENTROPY_LABEL_DEFAULT = Messages.getString("View.1"); //$NON-NLS-1$
	
	private Controller controller;
	
	private JMenuBar mainMenuBar;
	
	private JLabel configLabel;
	
	private JMenu fileMenu;
	
	private JMenuItem configMenuItem;
	
	private JMenuItem closeMenuItem;
	
	private JTextField passwordTextField;
	
	private GradientPanel panel;
	
	private JLabel entropyLabel;
	
	private JTextField md5TextField;
	
	private JTextField sha1TextField;
	
	private JTextField sha256TextField;
	
	private JTextField sha512TextField;
	
	private JButton validateButton;
	
	private JButton cancelButton;
	
	public View(Controller controller) {
		this.controller = controller;
		setTitle(Messages.getString("View.2")); //$NON-NLS-1$
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setPreferredSize(new Dimension(340, 260));
		init();
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
	}

	private LayoutManager initLayout() {
		final double p = TableLayoutConstants.PREFERRED;
		final double[] cols = new double[] {p, p, p, p, p};
		final double[] rows = new double[] {p, p, p, p, p};
		final TableLayout layout = new TableLayout(cols, rows);
		layout.setHGap(5);
		layout.setVGap(5);
		return layout;
	}

	private void init() {
		add(getMainMenuBar(), BorderLayout.NORTH);
		add(new JScrollPane(getContentPanel()), BorderLayout.CENTER);
	}

	private JPanel getContentPanel() {
		final JPanel panel = new JPanel();
		panel.setLayout(initLayout());
		panel.add(new JLabel(Messages.getString("View.3")), new TableLayoutConstraints(0, 1)); //$NON-NLS-1$
		panel.add(getPasswordTextField(), new TableLayoutConstraints(1, 1, 4, 1));
		panel.add(getPanel(), new TableLayoutConstraints(0, 2, 3, 2));
		panel.add(getEntropyLabel(), new TableLayoutConstraints(4, 2));
		panel.add(wrapWithScrollPane(getHashPanel()), new TableLayoutConstraints(0, 3, 4, 3));
		panel.add(getValidateButton(), new TableLayoutConstraints(0, 4, 2, 4));
		panel.add(getCancelButton(), new TableLayoutConstraints(3, 4, 4, 4));
		return panel;
	}
	
	private JScrollPane wrapWithScrollPane(Component component) {
		final JScrollPane jScrollPane = new JScrollPane(component);
		final JScrollBar bar = jScrollPane.getHorizontalScrollBar();
		bar.setValue(0);
		jScrollPane.setHorizontalScrollBar(bar);
		return jScrollPane;
	}

	private JPanel getHashPanel() {
		final double p = TableLayout.PREFERRED;
		final double[] cols = new double[] {p, TableLayout.FILL};
		final double[] rows = new double[] {p, p, p, p};
		final TableLayout layout = new TableLayout(cols, rows);
		layout.setHGap(2);
		layout.setVGap(2);
		
		final JPanel hashPanel = new JPanel(layout);
		hashPanel.add(createLabel(Messages.getString("View.4")), new TableLayoutConstraints(0, 0)); //$NON-NLS-1$
		hashPanel.add(getMd5TextField(),  new TableLayoutConstraints(1, 0));
		hashPanel.add(createLabel(Messages.getString("View.5")), new TableLayoutConstraints(0, 1)); //$NON-NLS-1$
		hashPanel.add(getSha1TextField(),  new TableLayoutConstraints(1, 1));
		hashPanel.add(createLabel(Messages.getString("View.6")), new TableLayoutConstraints(0, 2)); //$NON-NLS-1$
		hashPanel.add(getSha256TextField(),  new TableLayoutConstraints(1, 2));
		hashPanel.add(createLabel(Messages.getString("View.7")), new TableLayoutConstraints(0, 3)); //$NON-NLS-1$
		hashPanel.add(getSha512TextField(),  new TableLayoutConstraints(1, 3));
		
		return hashPanel;
	}
	
	private JLabel createLabel(final String text) {
		final JLabel label = new JLabel(text);
		label.setOpaque(true);
		return label;
	}

	public JTextField getPasswordTextField() {
		if (passwordTextField == null) {
			passwordTextField = new JTextField();
			passwordTextField.setColumns(20);
			passwordTextField.addKeyListener(new KeyAdapter() {
				@Override
				public void keyTyped(KeyEvent e) {
					final JTextField field = (JTextField) e.getComponent();
					String pass = field.getText();
					final char c = e.getKeyChar();
					if (!CharUtils.isAsciiControl(c)) {
						pass += c;
					}
					controller.actionCalculateHashAndEntropy(pass);
				}
			});
		}
		return passwordTextField;
	}

	public GradientPanel getPanel() {
		if (panel == null) {
			panel = new GradientPanel();
			panel.setPreferredSize(new Dimension(200, 20));
			panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
			panel.setEntropy(0);
		}
		return panel;
	}

	public JLabel getEntropyLabel() {
		if (entropyLabel == null) {
			entropyLabel = new JLabel(ENTROPY_LABEL_DEFAULT);
		}
		return entropyLabel;
	}

	public JTextField getMd5TextField() {
		if (md5TextField == null) {
			md5TextField = new JTextField();
			md5TextField.setPreferredSize(new Dimension(40, 20));
			md5TextField.setEditable(false);
			md5TextField.setToolTipText(TEXTFIELD_TOOL_TIP);
			md5TextField.setName(Messages.getString("View.9")); //$NON-NLS-1$
			md5TextField.addMouseListener(new ShowFullHashCodeAdapter());
		}
		return md5TextField;
	}

	public JTextField getSha1TextField() {
		if (sha1TextField == null) {
			sha1TextField = new JTextField();
			sha1TextField.setPreferredSize(new Dimension(40, 20));
			sha1TextField.setEditable(false);
			sha1TextField.setToolTipText(TEXTFIELD_TOOL_TIP);
			sha1TextField.setName(Messages.getString("View.10")); //$NON-NLS-1$
			sha1TextField.addMouseListener(new ShowFullHashCodeAdapter());
		}
		return sha1TextField;
	}

	public JTextField getSha256TextField() {
		if (sha256TextField == null) {
			sha256TextField = new JTextField();
			sha256TextField.setPreferredSize(new Dimension(40, 20));
			sha256TextField.setEditable(false);
			sha256TextField.setToolTipText(TEXTFIELD_TOOL_TIP);
			sha256TextField.setName(Messages.getString("View.11")); //$NON-NLS-1$
			sha256TextField.addMouseListener(new ShowFullHashCodeAdapter());
		}
		return sha256TextField;
	}

	public JTextField getSha512TextField() {
		if (sha512TextField == null) {
			sha512TextField = new JTextField();
			sha512TextField.setPreferredSize(new Dimension(40, 20));
			sha512TextField.setEditable(false);
			sha512TextField.setToolTipText(TEXTFIELD_TOOL_TIP);
			sha512TextField.setName(Messages.getString("View.12")); //$NON-NLS-1$
			sha512TextField.addMouseListener(new ShowFullHashCodeAdapter());
		}
		return sha512TextField;
	}

	public JButton getValidateButton() {
		if (validateButton == null) {
			validateButton = new JButton(Messages.getString("View.13")); //$NON-NLS-1$
			validateButton.setMnemonic(KeyEvent.VK_P);
			validateButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					controller.actionValidate();
				}
			});
		}
		return validateButton;
	}

	public JButton getCancelButton() {
		if (cancelButton == null) {
			cancelButton = new JButton(Messages.getString("View.18")); //$NON-NLS-1$
			cancelButton.setMnemonic(KeyEvent.VK_S);
			cancelButton.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					controller.actionClose();
				}
			});
		}
		return cancelButton;
	}
	
	
	
	public JMenuBar getMainMenuBar() {
		if (mainMenuBar == null) {
			mainMenuBar = new JMenuBar();
			mainMenuBar.add(getFileMenu());
			mainMenuBar.add(new JSeparator(JSeparator.VERTICAL));
			mainMenuBar.add(getConfigLabel(), -1);
		}
		return mainMenuBar;
	}

	public JMenu getFileMenu() {
		if (fileMenu == null) {
			fileMenu = new JMenu(Messages.getString("View.19")); //$NON-NLS-1$
			fileMenu.setMnemonic(KeyEvent.VK_D);
			fileMenu.add(getConfigMenuItem());
			fileMenu.add(new JSeparator());
			fileMenu.add(getCloseMenuItem());
		}
		return fileMenu;
	}
	
	public JMenuItem getConfigMenuItem() {
		if (configMenuItem == null) {
			configMenuItem = new JMenuItem(Messages.getString("View.22"));
			configMenuItem.setMnemonic(KeyEvent.VK_K);
			configMenuItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					controller.actionConfigView();
				}
			});
		}
		return configMenuItem;
	}

	public JMenuItem getCloseMenuItem() {
		if (closeMenuItem == null) {
			closeMenuItem = new JMenuItem(Messages.getString("View.20")); //$NON-NLS-1$
			closeMenuItem.setMnemonic(KeyEvent.VK_S);
			closeMenuItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					controller.actionClose();
				}
			});
		}
		return closeMenuItem;
	}
	
	public JLabel getConfigLabel() {
		if (configLabel == null) {
			configLabel = new JLabel();
			configLabel.setToolTipText(Messages.getString("View.23"));
		}
		return configLabel;
	}

	private class ShowFullHashCodeAdapter extends MouseAdapter {
		@Override
		public void mouseClicked(MouseEvent e) {
			if (e.getClickCount() == 2) {
				final JTextField field = (JTextField) e.getComponent();
				final String string = field.getText();
				if (string != null && !string.isEmpty()) {
					JOptionPane.showMessageDialog(e.getComponent(), Messages.getString("View.21", field.getName(), string)); //$NON-NLS-1$
				}
			}
		}
	}
}
